'''
作者：Zion Loh
时间：2025年7月7日
版权: MIT
使用源代码请附带版权信息！
'''

import tkinter as tk
from tkinter import filedialog, ttk, messagebox
from tkinterdnd2 import DND_FILES, TkinterDnD
from collections import Counter
from docx import Document
import matplotlib.pyplot as plt
from wordcloud import WordCloud
import re, os

class WordCounterApp:
    def __init__(self, root):
        self.root = root
        self.root.title("高频词统计工具  作者：ZionLoh")
        self.center_window(800, 600)  # 窗体居中
        self.create_widgets()

    def center_window(self, width, height):
        # 获取屏幕宽高
        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()
        
        # 计算居中位置
        position_top = int(screen_height / 2 - height / 2)
        position_right = int(screen_width / 2 - width / 2)
        
        # 设置窗体位置
        self.root.geometry(f'{width}x{height}+{position_right}+{position_top}')

    def create_widgets(self):
        # 文件路径输入框
        self.path_var = tk.StringVar()
        path_frame = ttk.Frame(self.root)
        path_frame.pack(pady=10, fill='x', padx=10)

        entry = ttk.Entry(path_frame, textvariable=self.path_var)
        entry.pack(side='left', fill='x', expand=True)
        entry.drop_target_register(DND_FILES)
        entry.dnd_bind('<<Drop>>', self.on_drop)

        ttk.Button(path_frame, text="选择文件", command=self.select_file).pack(side='left', padx=5)
        ttk.Button(path_frame, text="分析", command=self.analyze).pack(side='left')

        # 表格显示高频词
        self.tree = ttk.Treeview(self.root, columns=("词汇", "词频", "占比"), show="headings", height=15)
        self.tree.heading("词汇", text="词汇", command=lambda: self.sort_by_column(0, False))  # 可点击排序
        self.tree.heading("词频", text="词频", command=lambda: self.sort_by_column(1, False))  # 可点击排序
        self.tree.heading("占比", text="占比", command=lambda: self.sort_by_column(2, False))  # 可点击排序
        self.tree.pack(fill='both', expand=True, padx=10, pady=10)

    def on_drop(self, event):
        files = self.root.tk.splitlist(event.data)
        if files:
            self.path_var.set(files[0])

    def select_file(self):
        path = filedialog.askopenfilename(filetypes=[("Text files", "*.txt"), ("Word files", "*.docx")])
        if path:
            self.path_var.set(path)

    def read_file(self, path):
        ext = os.path.splitext(path)[-1].lower()
        if ext == '.txt':
            with open(path, "r", encoding="utf-8", errors='ignore') as f:
                return f.read()
        elif ext == '.docx':
            doc = Document(path)
            return "\n".join([para.text for para in doc.paragraphs])
        else:
            raise ValueError("只支持 txt 和 docx 文件")

    def tokenize(self, text):
        # 可拓展为中文分词，如 jieba
        words = re.findall(r'\b\w+\b', text.lower())
        return words

    def analyze(self):
        path = self.path_var.get()
        if not os.path.isfile(path):
            messagebox.showerror("错误", "无效的文件路径")
            return

        try:
            text = self.read_file(path)
            words = self.tokenize(text)
            total = len(words)
            counter = Counter(words)
            self.display_result(counter, total)
        except Exception as e:
            messagebox.showerror("错误", str(e))

    def display_result(self, counter, total_words):
        # 清空表格
        for row in self.tree.get_children():
            self.tree.delete(row)

        for word, count in counter.most_common(100):
            percent = f"{count / total_words:.2%}"
            self.tree.insert('', 'end', values=(word, count, percent))

        self.show_wordcloud(counter)

    def show_wordcloud(self, counter):
        # 中文字体路径（根据系统调整）
        font_path = "C:/Windows/Fonts/simhei.ttf"  # 黑体字体路径，可换成你系统中的其他中文字体

        # 更新 matplotlib 默认字体配置
        plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置默认字体为黑体
        plt.rcParams['axes.unicode_minus'] = False   # 解决负号显示问题

        plt.figure(figsize=(10, 4))
        wc = WordCloud(
            font_path=font_path,
            width=800,
            height=300,
            background_color="white"
        ).generate_from_frequencies(counter)

        plt.imshow(wc, interpolation='bilinear')
        plt.axis("off")
        plt.title("词云图", fontsize=16)  # 现在标题 "词云图" 应该能正确显示
        plt.tight_layout()
        plt.show()

    def sort_by_column(self, col, reverse):
        # 获取当前树视图的列数据
        items = [(self.tree.item(item)["values"], item) for item in self.tree.get_children('')]
        items.sort(key=lambda x: x[0][col], reverse=reverse)
        
        # 清空当前表格内容
        for item in self.tree.get_children():
            self.tree.delete(item)

        # 插入排序后的数据
        for item in items:
            self.tree.insert('', 'end', values=item[0])

        # 更新排序方向
        self.tree.heading(self.tree['columns'][col], command=lambda _col=col: self.sort_by_column(_col, not reverse))

if __name__ == "__main__":
    root = TkinterDnD.Tk()
    app = WordCounterApp(root)
    root.mainloop()
